package com.wpx.log.core.handler;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import org.springframework.util.StringUtils;

import com.wpx.log.core.LogContext;
import com.wpx.log.core.LogRequestContext;
import com.wpx.log.core.annotation.OpLogInto;
import com.wpx.log.core.annotation.OpLogField;
import com.wpx.log.core.annotation.OpLogIgnore;
import com.wpx.log.core.annotation.OpLogUpdata;
import com.wpx.log.core.handler.field.equals.IFieldEqualsPolicy;
import com.wpx.log.core.handler.field.render.IFieldRenderPolicy;
import com.wpx.log.core.module.FieldUpdateInfo;
import com.wpx.log.util.Utils;

public class OpUpdateLogHandler implements ILogHandler {

	@Override
	public Object handler(LogContext logContext, LogRequestContext logRequestContext, Field logField) {
		Object old = logRequestContext.getOld();
		if(old == null || old.getClass().getAnnotation(OpLogUpdata.class) == null) {
			return null;
		}
		
		List<FieldUpdateInfo> infos = new ArrayList<FieldUpdateInfo>();
		Object nnew = logRequestContext.getNnew();
		doCompare(old, nnew, infos, logContext);
		return returnObject(infos);
	}


	private void doCompare(Object old, Object nnew, List<FieldUpdateInfo> infos, LogContext logContext) {
		if(old == null || nnew == null) {
			return;
		}

		try {
			Field[] fields = Utils.getMemberField(old.getClass());
			for (Field field : fields) {
				if(field.getAnnotation(OpLogIgnore.class) != null) {
					continue;
				}

				field.setAccessible(true);
				Object oldValue = field.get(old);
				Object newValue = field.get(nnew);

				if(field.getAnnotation(OpLogInto.class) != null) {
					doCompare(oldValue, newValue, infos, logContext);
					continue;
				}

				OpLogField opLogField = field.getAnnotation(OpLogField.class);
				IFieldEqualsPolicy equalsPolicy = null;
				if(opLogField != null) {
					equalsPolicy = logContext.getFieldEqualsPolicy(opLogField.equalsPolicy());
				}
				if(equalsPolicy == null) {
					equalsPolicy = logContext.getFieldEqualsPolicy(field.getType());
				}
				if(equalsPolicy == null) {
					equalsPolicy = logContext.getFieldEqualsPolicy(Object.class);
				}
				
				if(equalsPolicy.equals(newValue, oldValue) == false) {
					FieldUpdateInfo info = new FieldUpdateInfo();
					String name = field.getName();;
					if(opLogField != null && !StringUtils.isEmpty(opLogField.value())) {
						name = opLogField.value();
					}
					info.setName(name);
					
					IFieldRenderPolicy fieldRenderPolicy = null;
					if(opLogField != null) {
						fieldRenderPolicy = logContext.getFieldRenderPolicy(opLogField.renderPolicy());
					}
					if(fieldRenderPolicy == null) {
						fieldRenderPolicy = logContext.getFieldRenderPolicy(field.getType());
					}
					if(fieldRenderPolicy == null) {
						fieldRenderPolicy = logContext.getFieldRenderPolicy(Object.class);
					}
					info.setOldValue(fieldRenderPolicy.render(oldValue, opLogField));
					info.setNewValue(fieldRenderPolicy.render(newValue, opLogField));
					info.setDataType(fieldRenderPolicy.dataType());
					infos.add(info);
				}	
			}

		} catch (Exception e) {
			e.printStackTrace();
			new RuntimeException("更新比较处理 异常", e);
		}

	}

	/**
	 * 可以重写该方法  装换成 自定义的具体类型或格式
	 */
	public Object returnObject(List<FieldUpdateInfo> infos) {
		return infos.toArray(new FieldUpdateInfo[infos.size()]);
	}

}
